/*
 * libc.c
 */

#include <libc.h>
#include <io.h>
#include <error.h>
/* Wrapper of exit system call*/
int exit()
{
	int res;	 
	__asm__ __volatile__(
		"movl $1,%%eax\n"
		"int $0x80\n"
		: "=a" (res)
		: 
		: "memory"); 
	if (res>=0) return res;
	else
	{
		errno=-res; 	
		return -1;
	}
}
/* Wrapper of fork system call*/
int fork()
{
	int res;
	__asm__ __volatile__(	
		"movl $2, %%eax\n"
		"int $0x80\n"
		: "=a" (res)
		: 
		: "memory"); 
	if (res>=0)
		return res;
	else
	{
		errno=-res; 	
		return -1;
	}
}

/* Wrapper of  write system call*/
int write(int fd,char *buffer,int size)
{
	int res;

	/*start of asm code*/
	__asm__ __volatile__(	
	/* set the sys_call indentification number (writer -> 4)*/
		"movl $4, %%eax\n"
	/*trigger the interrupt*/
		"int $0x80\n"
	/*output, input and modified registers*/
		: "=a" (res)
		: "b" (fd), "c" (buffer), "d"(size)); 
	/* end of asm code */

	if (res>=0)
		return res;
	else
	{
		errno=-res; 	
		return -1;
	}
}
/* Wrapper of getpid system call*/
int getpid()
{
	int res;	 

	__asm__ __volatile__(
		"movl $20,%%eax\n"
		"int $0x80\n"
		: "=a" (res)
		: 
		: "memory"); 
	if (res>=0) return res;
	else
	{
		errno=-res; 	
		return -1;
	}
}	
/* Wrapper of sem_init system call*/
int sem_init(int n_sem, unsigned int value)
{
	int res;	 
	__asm__ __volatile__(
		"movl $21,%%eax\n"
		"int $0x80\n"
		: "=a" (res)
		: "b" (n_sem), "c" (value)
		: "memory"); 
	if (res>=0) return res;
	else
	{
		errno=-res; 	
		return -1;
	}
}	
/* Wrapper of sem_wait system call*/
int sem_wait(int n_sem)
{
	int res;	 
	__asm__ __volatile__(
		"movl $22,%%eax\n"
		"int $0x80\n"
		: "=a" (res)
		: "b" (n_sem)
		: "memory"); 
	if (res>=0) return res;
	else
	{
		errno=-res; 	
		return -1;
	}
}	
/* Wrapper of sem_signal system call*/
int sem_signal(int n_sem)
{
	int res;	 
	
	__asm__ __volatile__(
		"movl $23,%%eax\n"
		"int $0x80\n"
		: "=a" (res)
		: "b" (n_sem)
		: "memory"); 
	if (res>=0) return res;
	else
	{
		errno=-res; 	
		return -1;
	}
}	

/* Wrapper of sem_destroy system call*/
int sem_destroy(int n_sem)
{
	int res;	 
	
	__asm__ __volatile__(
		"movl $24,%%eax\n"
		"int $0x80\n"
		: "=a" (res)
		: "b" (n_sem)
		: "memory"); 
	if (res>=0) return res;
	else
	{
		errno=-res; 	
		return -1;
	}
}	
/* Wrapper of nice system call*/
int nice(int quantum)
{
	int res;	 
	__asm__ __volatile__(
		"movl $34,%%eax\n"
		"int $0x80\n"
		: "=a" (res)
		: "b" (quantum)
		: "memory"); 
	if (res>=0) return res;
	else
	{
		errno=-res; 	
		return -1;
	}
}	

//Wrapper of get_stats system call
int get_stats(int pid, struct stats *st)
{
	int res;	 

	__asm__ __volatile__(
		"movl $35,%%eax\n" // get_stats (35) > eax
		"int $0x80\n"
		: "=a" (res)
		: "b" (pid), "c" (st)
		: "memory"); 
	if (res>=0) return res;
	else
	{
		errno=-res; 	
		return -1;
	}
}

void perror()
 {
	 char* err_msg;
 	 switch (errno)
 	 {
 	 case EPERM: err_msg = "Error EPERM: Operation not permitted\n"; break;
 	 case EINVAL: err_msg = "Error EINVAL: Invalid argument\n"; break;
 	 case EBADF: err_msg = "Error EBADF: Bad file number\n"; break;
 	 case ENOSYS: err_msg = "Error ENOSYS: Function not implemented\n"; break;
	 case EFAULT: err_msg = "Error EFAULT: Invalid address\n"; break;
 	 default: err_msg = "Unknown type of error!\n";

 	 }
 	 int msg_size = strlen(err_msg);
	 write(1,err_msg,msg_size); //print the error if perror() is invoked
 }

int strlen(char* string) //function to determine the length of a string.
{
	int size = 0;
	while (string[size]!='\0') size++;
	return size;
}
